﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Rechargeable.Machines.Dto;
using Rechargeable.Products;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
using Volo.Abp.Threading;

namespace Rechargeable.Machines
{
    [Authorize]
    public class SerialNumberAppService : CrudAppService<SerialNumber, SerialNumberDto, Guid, PageAndSortedResultRequestSerialNumberDto, CreateSerialNumberDto, CreateSerialNumberDto>, ISerialNumberAppService
    {
        private IRepository<SerialNumber, Guid> _repositorySerialNumbers;
        private IRepository<Product, Guid> _repositoryProduct;
        private IRepository<ProductPrice, Guid> _repositoryProductPrices;
        private readonly IGuidGenerator _guidGenerator;

        public SerialNumberAppService(IRepository<SerialNumber, Guid> repositorySerialNumbers,
         IRepository<Product, Guid> repositoryProduct,
          IRepository<ProductPrice, Guid> repositoryProductPrices,
          IGuidGenerator guidGenerator) : base(repositorySerialNumbers)
        {
            _repositorySerialNumbers = repositorySerialNumbers;
            _repositoryProduct = repositoryProduct;
            _repositoryProductPrices = repositoryProductPrices;
            _guidGenerator = guidGenerator;
        }//

        public async Task<int> GetNotUseCount(PageAndSortedResultRequestSerialNumberDto inputDto)
        {
            return (await _repositorySerialNumbers.GetQueryableAsync()).WhereIf(inputDto.ProductId != Guid.Empty, q => q.ProductId == inputDto.ProductId).Where(q => q.UseTime == null && (q.MachineId == Guid.Empty || q.MachineId == null)).Count();
        }

        [Authorize]
        public async Task PostRechargesAsync(CreateSerialNumbersDto inputDto)
        {
            //var serialNumber = ObjectMapper.Map<CreateSerialNumberDto, SerialNumber>(inputDto);
            var product = (await _repositoryProduct.GetQueryableAsync()).Where(q => q.Id == inputDto.ProductId).FirstOrDefault();
            var productPrice = (await _repositoryProductPrices.GetQueryableAsync()).Where(q => q.Id == inputDto.ProductPriceId).FirstOrDefault();
            if (product == null)
                throw new UserFriendlyException("未找到对应的商品信息");
            if (productPrice == null)
                throw new UserFriendlyException("未找到对应的价格信息");
            if (product.Id != productPrice.ProductId)
                throw new UserFriendlyException("商品信息和价格信息不匹配");

            for (int i = 0; i < inputDto.Count; i++)
            {
                var serialNumber = new SerialNumber(_guidGenerator.Create());
                serialNumber.SaleUserId = CurrentUser.Id;
                serialNumber.Expire = productPrice.Day;
                serialNumber.UseTime = null;
                serialNumber.BuyUserId = inputDto.BuyUserId;
                serialNumber.MachineId = Guid.Empty;
                serialNumber.ProductId = inputDto.ProductId;
                serialNumber.ProductPriceId = inputDto.ProductPriceId;
                serialNumber.SaleUserId = CurrentUser.Id;
                serialNumber.CreateDesc = $"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")}，【{CurrentUser.UserName}】通过后台创建，充值备注:{inputDto.Desc}。";
                await _repositorySerialNumbers.InsertAsync(serialNumber);
            }
        }

        protected override async Task<IQueryable<SerialNumber>> CreateFilteredQueryAsync(PageAndSortedResultRequestSerialNumberDto input)
        {
            var query = await base.CreateFilteredQueryAsync(input);
            if (input.ProductId.HasValue && input.ProductId.Value != Guid.Empty)
                query = query.Where(q => q.ProductId == input.ProductId.Value);

            Guid g = Guid.Empty;
            if (!string.IsNullOrEmpty(input.Key) && Guid.TryParse(input.Key, out g))
            {
                query = query.Where(q => q.Id == g || q.MachineId == g);
            }
            return query.Where(q => q.BuyUserId == CurrentUser.Id);
        }
    }
}
